// Package logs.
// creator 2022-03-23 00:21:45
// Author  zhenxinma.
package log

import (
	"bytes"
	"fmt"
	"github.com/sirupsen/logrus"
	"os"
	"runtime"
	"strconv"
	"strings"
	"sync/atomic"
)

// 日志组件.

var log = logrus.New()

// 带f的重新构造一个即可.

var logf = logrus.New()

func init() {
	name, _ := os.Hostname()
	fm := &LogFormat{
		HostName:          name,
		TimestampFormat:   "2006-01-02 15:04:05.999",
		CallerFileTrimLen: 0,
	}

	log.SetFormatter(fm)
	log.AddHook(&DefaultHook{
		Skip: 8,
	})
	log.SetOutput(os.Stdout)

	fmf := &LogFormat{
		HostName:          name,
		TimestampFormat:   "2006-01-02 15:04:05.999",
		CallerFileTrimLen: 0,
	}
	// 初始化logf.
	logf.SetFormatter(fmf)
	logf.AddHook(&DefaultHook{
		Skip: 9,
	})
	logf.SetOutput(os.Stdout)
}

// DefaultHook 自己实现Hook.
type DefaultHook struct {
	Skip int
}

func (d *DefaultHook) Fire(entry *logrus.Entry) error {
	//entry.Data["HostName"] = "zhenxinmaa"
	//entry.Data["Fire"] = "Hello Word"
	// 实现行数.
	// 返回上层调用的函数.
	// info 8
	// infof 9
	pc, file, line, ok := runtime.Caller(d.Skip)
	if ok {
		// 函数栈用尽了.
		// /src/main.go method 98
		funcName := runtime.FuncForPC(pc).Name()
		lineStr := file + " " + funcName + " " + strconv.Itoa(line)
		entry.Data["LogPath"] = lineStr
	} else {
		entry.Data["LogPath"] = ""
	}
	return nil
}

func (d *DefaultHook) Levels() []logrus.Level {
	return logrus.AllLevels
}

type LogFormat struct {
	HostName          string
	TimestampFormat   string
	CallerFileTrimLen int
	PrintCaller       bool
	devopsTrimLen     atomic.Value
}

//Format for log format
func (f *LogFormat) Format(entry *logrus.Entry) ([]byte, error) {
	logIgnore, ok := entry.Data["__logignore__"]
	if ok && logIgnore != nil && logIgnore.(bool) {
		return nil, nil
	}

	var b *bytes.Buffer

	if entry.Buffer != nil {
		b = entry.Buffer
	} else {
		b = &bytes.Buffer{}
	}

	b.WriteString(entry.Time.Format(f.TimestampFormat))

	b.WriteString(" [")
	b.WriteString(f.HostName)
	b.WriteString("]")

	b.WriteByte('[')
	b.WriteString(strings.ToUpper(entry.Level.String()))
	b.WriteString("]")

	logTag, ok := entry.Data["__logtag__"]
	if ok {
		b.WriteByte('[')
		b.WriteString(logTag.(string))
		b.WriteString("] ")
	}

	if entry.Message != "" {
		b.WriteString(entry.Message)
	}

	hasData := false
	for key, value := range entry.Data {
		if key == "__logtag__" {
			continue
		}

		if !hasData {
			hasData = true
			b.WriteString(" || ")
		}

		b.WriteString(key)
		b.WriteByte('=')
		fmt.Fprint(b, value)
		b.WriteString(", ")
	}

	b.WriteByte('\n')
	return b.Bytes(), nil
}

// Info 还是需要自己实现.
func Info(args ...interface{}) {
	log.Info(args)
}

func Infof(format string, args ...interface{}) {
	logf.Infof(format, args)
}

func Warn(args ...interface{}) {
	log.Warn(args)
}

func Warnf(format string, args ...interface{}) {
	logf.Warnf(format, args)
}

func Error(args ...interface{}) {
	log.Error(args)
}

func Errorf(format string, args ...interface{}) {
	logf.Errorf(format, args)
}
